package org.setamv.springcloud.controller;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentMapTest {


    public static Object get(Map<String, Object> map, String key) {
        return map.get(key);
    }

    public static Object put(Map<String, Object> map, String key, Object val) {
        return map.put(key, val);
    }

    /**
     *
     * @param map
     * @param capacity
     * @param opTimes 测试的Map操作次数，一次操作包括 往map插入一个值，然后读出一个值
     * @param threadCnt
     */
    public static void test(String tag, Map<String, Object> map, int capacity, int opTimes, int threadCnt) throws Exception {
        List<String> keys = new ArrayList<>(capacity);
        for (int i = 0; i < capacity; i++) {
            keys.add(UUID.randomUUID().toString());
        }

        Thread[] threads= new Thread[threadCnt];
        Long[] costTimes = new Long[threadCnt];
        for (int i = 0; i < threadCnt; i++) {
            final int threadIdx = i;
            threads[i] = new Thread(() -> {
                long startTime = System.currentTimeMillis();
                for (int j = 0; j < opTimes; j++) {
                    int putIdx = j % capacity;
                    int getIdx = capacity - putIdx - 1;
                    String putKey = keys.get(putIdx);
                    String getKey = keys.get(getIdx);
                    map.put(putKey, putKey);
                    map.get(getKey);
                }
                long endTime = System.currentTimeMillis();
                costTimes[threadIdx] = endTime - startTime;
            });
        }

        for (Thread thread : threads) {
            thread.start();
        }

        for (Thread thread : threads) {
            thread.join();
        }

        long totalCostTime = 0L;
        for (Long costTime : costTimes) {
            totalCostTime += costTime;
        }
        System.out.println(tag + " cost time: " + totalCostTime);
    }

    public static void main(String[] args) throws Exception {
        int opTimes = 100000;
        int capacity = 10000;
        int threadCnt = 2000;

        Map<String, Object> hashtable = new Hashtable<>(capacity);
        Map<String, Object> concurrentMap = new ConcurrentHashMap<>(capacity);

        test("hashtable", hashtable, capacity, opTimes, 20);

        Thread.sleep(1000);

        test("concurrentMap", concurrentMap, capacity, opTimes, 20);

    }
}
